package com.sun.mongodb.core.service;


import com.sun.mongodb.core.entity.BaseMongo;
import com.sun.mongodb.core.query.AggregationWrapper;
import com.sun.mongodb.core.query.CriteriaWrapper;
import com.sun.mongodb.core.params.LookUpParam;
import com.sun.mongodb.core.reflection.SerializableFunction;
import com.sun.mongodb.core.util.PageUtils;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.lang.Nullable;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by Administrator on 2021/8/17.
 */
public interface BaseMongoService<T extends BaseMongo> {
    int DEFAULT_BATCH_SIZE = 1000;

    /**
     * 新增
     * @param entity
     * @return
     */
    T save(T entity);
    /**
     * 批量新增
     * @param list
     * @return
     */
    Collection<T> saveBatch(Collection<T> list);
    /**
     * 根据id删除
     * @param _id
     * @return
     */
    void removeById(Serializable _id);
    /**
     * 根据 条件删除
     * @param queryWrapper
     * @return
     */
    boolean remove(CriteriaWrapper queryWrapper);

    void removeByIds(Collection<? extends Serializable> idList);

    boolean updateById(T entity);

    boolean updateBatchById(Collection<T> entityList);

    /**
     * 修改所有满足条件的
     * @param entity
     * @param updateWrapper
     * @return
     */
    boolean update(T entity, CriteriaWrapper updateWrapper);
    /**
     * 修改 第一条 满足条件的
     * @param entity
     * @param updateWrapper
     * @return
     */
    boolean updateSingle(T entity, CriteriaWrapper updateWrapper);


    /**
     * 修改所有满足条件的
     * @param updateWrapper
     * @return
     */
    boolean update(Update update, CriteriaWrapper updateWrapper);
    /**
     * 修改 第一条 满足条件的
     * @param updateWrapper
     * @return
     */
    boolean updateSingle(Update update, CriteriaWrapper updateWrapper);

    boolean saveOrUpdate(T var1);

    T getById(Serializable id);

    List<T> listByIds(Collection<? extends Serializable> idList);

    T getOne(CriteriaWrapper queryWrapper);

    long count();

    long count(CriteriaWrapper queryWrapper);

    List<T> list(CriteriaWrapper queryWrapper);

    List<T> list();

    PageUtils<T> page(PageUtils<?> page);

    PageUtils<T> page(PageUtils<?> page,CriteriaWrapper queryWrapper);

    /**
     * 找到并删除
     * @param updateWrapper
     * @return  找到的原数据
     */
    T findAndRemove(CriteriaWrapper updateWrapper);
    /**
     * 找到并替换
     * @param updateWrapper
     * @return  找到的原数据
     */
    public T findAndReplace(CriteriaWrapper updateWrapper,T t);

    /**
     * 聚合查询
     * @return
     */
    List<T> aggregate(Aggregation agg);

    /**
     * 聚合查询
     * @param agg
     * @param clazz  返回类
     * @return
     */
    <V> List<V> aggregate(Aggregation agg,Class<V> clazz);

    /**
     * 聚合查询
     * @return
     */
    List<T> aggregate(AggregationWrapper wrapper);

    /**
     *  $lookup  对同一数据库中的另一个集合执行左外连接
     * @param joinClazz    关联表类
     * @param localColumn  主表-关联字段
     * @param foreignColumn  关联表-关联字段
     * @param as  别名
     * @return
     */
   <E,R> AggregationOperation lookup(Class<?> joinClazz, SerializableFunction<E, R> localColumn,  SerializableFunction<E, R> foreignColumn, String as);

    /**
     * 聚合管道函数  $graphLookup  图查询   对集合执行递归搜索。
     * @param joinClazz    collection 表名
     * @param startWith
     * @param connectFrom  主表字段-字段名
     * @param connectTo     关联字段名
     * @param as     别名
     * @param maxDepth   递归深度
     * @param depthField  深度字段
     * @param criteria  搜索范围查询条件
     * @return
     */
    <E,R> AggregationOperation graphLookup(Class<?> joinClazz, List<Object> startWith, SerializableFunction<E, R> connectFrom, SerializableFunction<E, R> connectTo, String as, @Nullable
            Long maxDepth, @Nullable SerializableFunction<E, R> depthField, @Nullable CriteriaWrapper criteria);

    default <V> List<V> listObjs(CriteriaWrapper queryWrapper, Function<? super Object, V> mapper) {
        return (List)this.list(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
    }
    default <V> List<V> listObjs(Function<? super Object, V> mapper) {
        return this.listObjs(CriteriaWrapper.emptyWrapper(), mapper);
    }

    public String getEntityCollectionName(Class<?> joinClazz);

    default List<T> leftJoinList(CriteriaWrapper queryWrapper,LookUpParam lookUpParam){
        return (List)leftJoinList(queryWrapper, Arrays.asList(lookUpParam));
    }
    public List<T> leftJoinList(CriteriaWrapper queryWrapper,List<LookUpParam> lookUpParamList);


}
